package org.softmed.rest.server.defaults.generation;

import java.lang.reflect.Field;
import java.util.List;
import org.softmed.reflection.utils.FieldInfo;
import org.softmed.reflection.utils.ReflectionUtil;
import org.softmed.rest.generation.scafold.AppConfig;
import org.softmed.rest.generation.scafold.ModConfig;
import org.softmed.rest.generation.scafold.build.ApplicationProcessor;

public class DefaultClassValidator implements ApplicationProcessor {

	ReflectionUtil util = new ReflectionUtil();

	@Override
	public void process(List<AppConfig> apps) throws Throwable {
		for (AppConfig appConfig : apps) {
			validate(appConfig);
		}

	}

	private void validate(AppConfig appConfig) throws Throwable {
		List<ModConfig> mods = appConfig.getModules();
		for (ModConfig modConfig : mods) {
			List<Class> classes = appConfig.getClasses();
			for (Class type : classes) {
				List<FieldInfo> fieldInfos = util.getFieldInfos(type);
				for (FieldInfo fieldInfo : fieldInfos) {
					if (util.isPrimitiveOrProxyOrString(fieldInfo.getType()))
						continue;

					if (List.class.isAssignableFrom(fieldInfo.getType())) {
						Field field = util.getField(type, fieldInfo.getName());
						Class listType = util.isSpecificList(field);

						if (listType == null) {
							write("Class " + type.getCanonicalName()
									+ " has a non-generic list field named "
									+ fieldInfo.getName() + " in Module "
									+ modConfig.getName() + " of Application "
									+ appConfig.getName() + " ");
							continue;
						}

						if (util.isPrimitiveOrProxyOrString(listType))
							continue;

						// if (!classes.contains(listType)) {
						if (!containsClass(classes, listType)) {

							write("Class " + type.getCanonicalName()
									+ " of module " + modConfig.getName()
									+ " has a field named "
									+ fieldInfo.getName()
									+ " which is a generic list of a class - "
									+ listType.getCanonicalName()
									+ " - not registered in the Application "
									+ appConfig.getName() + " ");
							continue;
						}
						// System.out.println("list field");

						continue;
					}

					// if (!classes.contains(fieldInfo.getType())) {
					if (!containsClass(classes, fieldInfo.getType())) {

						write("Class " + type.getCanonicalName()
								+ " of module " + modConfig.getName()
								+ " has a field named " + fieldInfo.getName()
								+ " which is of a class - "
								+ fieldInfo.getType().getCanonicalName()
								+ " - not registered in the Application "
								+ appConfig.getName() + " ");
						continue;
					}

				}
			}
		}
	}

	protected boolean containsClass(List<Class> classes, Class target) {
		for (Class type : classes) {
			if (type.getCanonicalName().equals(target.getCanonicalName()))
				return true;
		}
		return false;
	}

	public void write(String msg) {
		System.err.println(msg);
	}

}
